import { dirname } from "path";
import { BaseError } from "./entity/BaseEntity";
import { EnumCode } from "./entity/Code";
import { Config, processArg } from "./entity/Config";
import { IGlobal } from "./entity/Global";
import { BaseService } from "./plus/httpServer/BaseService";
import { PlusHttpServer } from "./plus/PlusHttpServer";
import { PlusRedis } from "./plus/PlusRedis";
import { PlusSchedule } from "./plus/PlusSchedule";
import { PlusSequelize } from "./plus/PlusSequelize";
import { PlusWsServer } from "./plus/PlusWsServer";
import { WsBaseService } from "./plus/websocket/server/WsBaseService";
import { PlusMgr } from "./PlusMgr";
import { ClsUtils } from "./utils/ClsUtils";
import { FileUtils } from "./utils/FileUtils";
import { HttpUtils } from "./utils/HttpUtils";
import { LogUtils } from "./utils/LogUtils";
import { StringUtils } from "./utils/StringUtils";
import { TimeUtils } from "./utils/TimeUtils";
export { PlusMgr, PlusHttpServer, PlusRedis, processArg, IGlobal, BaseService, EnumCode, PlusSchedule, PlusSequelize, BaseError, PlusWsServer, WsBaseService };
export { HttpUtils, StringUtils, FileUtils, TimeUtils, LogUtils, ClsUtils };

declare var global: IGlobal;
export class App {
    start() {
        let rootFile = process.argv[1];
        let rootDir = dirname(rootFile);
        global.rootPath = rootDir;
        let config = <any>new Config(processArg.env, processArg.main)
        global.log = new LogUtils(rootDir, "/opt/logs", config.logConfig);
        global.config = config;
        global.Debug = config.Debug;
        config.on("change", this.mConfigUpdate.bind(this));
        this.mConfigUpdate();
        this.handlerException();
        global.log.info("开始启动服务:" + JSON.stringify(processArg));
        let plusMgr = new PlusMgr();
        global.plus = plusMgr;
        plusMgr.on("complete", this.mOnComplete.bind(this));
        this.mInitPlus(plusMgr);
        plusMgr.start();
    }

    protected mInitPlus(plusMgr: PlusMgr) {
        let config = global.config;
        if (config.sql) plusMgr.registPlus(new PlusSequelize(config.sql, global.rootPath + "/model"));
        plusMgr.registPlus(new PlusSchedule(global.rootPath + "/schedule"));
        if (config.redis) plusMgr.registPlus(new PlusRedis(config.redis));
        let port = processArg.port || config.port;
        if (port) {
            plusMgr.registPlus(new PlusHttpServer(port, global.rootPath + "/controller"));
        }
        let wsPort = processArg.wsPort || config.wsPort;
        if (wsPort) {
            plusMgr.registPlus(new PlusWsServer(PlusWsServer.NAME,wsPort, global.rootPath + "/wsController"));
        }
    }

    protected async mOnComplete() {

    }

    protected mConfigUpdate() {
        global.log.updateLogLevel(global.config.logLevels);
    }

    /**
     * 进程异常处理
     */
    private handlerException() {
        process.on('uncaughtException', function (err: Error) {
            if (typeof err === 'object') {
                if (err.message) {
                    global.log.error('ERROR: ' + err.message);
                }
                if (err.stack) {
                    global.log.error(err.stack + " ERROR TIME: " + new Date());
                }
            }
            else {
                global.log.error('argument is not an object');
            }
            try {
                var killTimer = setTimeout(function () {
                    process.exit(1);
                }, 30000);
                killTimer.unref();
            }
            catch (e) {
                global.log.error('error when exit' + e.stack);
            }
        });
    }
}